/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cc.altius.security;

import cc.altius.domain.CustomUserDetails;
import cc.altius.domain.Role;
import cc.altius.domain.User;

import cc.altius.utils.LogUtils;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
import java.util.List;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author Akil Mahimwala
 */
@Service("customUserDetailsService")
public class CustomUserDetailsService implements UserDetailsService {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void setDataSource(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    @Override
    @Transactional(readOnly = true)
    public CustomUserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        String sqlString = "SELECT user.*,user_role.*   FROM user left join user_role on user_role.USER_ID=user.USER_ID WHERE USERNAME=?";
        String ipAddress = "";//((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes()).getRequest().getRemoteAddr();
        try {
            CustomUserDetails user = this.jdbcTemplate.queryForObject(sqlString, new Object[]{username}, new CustomUserDetailsService.CustomUserDetailsRowMapper());
            if (!user.isActive()) {
                LogUtils.accountInActive(ipAddress, user.getUsername());
            } else if (user.isPasswordExpired()) {
                // only insert the ROLE_BF_PASSWORD_EXPIRED
                LogUtils.debug("Credentials are Expired so only put in ROLE_BF_PASSWORD_EXPIRED into Authoirites");
                System.out.println("Credentials are Expired so only put in ROLE_BF_PASSWORD_EXPIRED into Authoirites");
                List<String> businessFunctions = new LinkedList<String>();
                businessFunctions.add("ROLE_BF_PASSWORD_EXPIRED");
                user.setBusinessFunction(businessFunctions);
            } else if (!user.isAccountNonLocked()) {
                LogUtils.accountLocked(ipAddress, user.getUsername());
            } else {
                sqlString = "SELECT BUSINESS_FUNCTION_ID FROM user_role LEFT JOIN role_business_function ON user_role.ROLE_ID=role_business_function.ROLE_ID WHERE user_role.USER_ID=?";
                user.setBusinessFunction(this.jdbcTemplate.queryForList(sqlString, new Object[]{user.getUserId()}, String.class));
            }
            return user;
        } catch (EmptyResultDataAccessException erda) {
            throw new UsernameNotFoundException("Username not found");
        }
    }

    private class CustomUserDetailsRowMapper implements RowMapper<CustomUserDetails> {

        @Override
        public CustomUserDetails mapRow(ResultSet rs, int i) throws SQLException {
            User u = new User();
            CustomUserDetails user = new CustomUserDetails(u);
            Role r = new Role();
            r.setRoleId(rs.getString("ROLE_ID"));
            user.setRole(r);
            user.setDealerId(1);
            user.setUserId(rs.getInt("USER_ID"));
            user.setUsername(rs.getString("USERNAME"));
            user.setPassword(rs.getString("PASSWORD"));
            user.setActive(rs.getBoolean("ACTIVE"));
            user.setExpired(rs.getBoolean("EXPIRED"));
            user.setFailedAttempts(rs.getInt("FAILED_ATTEMPTS"));
            user.setExpiresOn(rs.getDate("EXPIRES_ON"));
            return user;
        }
    }
}
